/**************************************************************************
 *
 * Description : hb_auto_gpio.c
 * Author      : isen
 * Date        : 2020.10.10
 * Verson      : V1.0
 * Function    : 1,温度 定时 分段播报;
 *               2,音量控制自主修正,不发串口数据,静音所有声音停止;
 **************************************************************************/
#include "user_config.h"
#include "user_event.h"
#include "user_gpio.h"
#include "user_player.h"
#include "user_pwm.h"
#include "user_timer.h"
#include "user_uart.h"
#include "uni_hal_timer.h"
#include "user_flash.h"
#include "uni_audio_player.h"

#include "yfc_auto_gpio.c"
#include "yfc_parm.h"

//#define PA_EN_LV            1
//#define PA_DIS_LV           0

#define SYS_VOLUME_SET      (uni_u16)0X005A  //音量控制
#define SYS_PLAY_FB         (uni_u16)0X005B  //播报反馈(主动 手动)
#define SYS_FUN_SEL         (uni_u16)0X005C  //功能开关（开 关）
#define SYS_WAITUP_SEL      (uni_u16)0X005D  //识别屏蔽（）
#define SYS_DELAY_PA        (uni_u16)0X005E  //功放延时（）
#define SYS_PLAY_LIST       (uni_u16)0X005F  //主动播报选择（随机 对应）

#define PLAY_FB_VOLUME    (uni_u8)0X01
#define PLAY_FB_WAITUP    (uni_u8)0X02
#define PLAY_FB_CUSTOM    (uni_u8)0X03
#define PLAY_FB_EXIT      (uni_u8)0X04
#define PLAY_FB_MUTE      (uni_u8)0X05
#define PLAY_FB_ONCE      (uni_u8)0X06

#define AUTO_PLAY       (uni_u8)0x80
#define FUN_EN          (uni_u8)0x40
#define AUTO_LIST       (uni_u8)0x20

#define VOL_MAX     (uni_u16)0x0008
#define VOL_MID     (uni_u16)0x000a
#define VOL_MIN     (uni_u16)0x0009
#define VOL_UP      (uni_u16)0x0006
#define VOL_DOWN    (uni_u16)0x0007

#define ADDR_SYS_MIN      (uni_u16)0x005a
#define ADDR_SYS_MAX      (uni_u16)0x0095

#define ADDR_WAITUP_MIN      (uni_u16)0x001e
#define ADDR_WAITUP_MAX      (uni_u16)0x0027


#define BLOB_KEY_VOLUME   "SAVE_VOL"    //音量记忆名称
#define BLOB_KEY_SYS      "SAVE_SYS"     //系统功能名称

typedef enum { 
  pwm1=0x01,
  pwm2
}yfc_pwmSerial_t;


typedef struct {
  bool  enSend;       //发送使能
  bool  enRepeat;     //重复发送标记位
  bool bexecute;
  char data[UART_SEND_MAX];   //串口发送数组
  unsigned char num;          //g_uart_buf 发送数组的下标
  unsigned char serial;       //发送序号 自加
  unsigned int cntRepaet;     //已重复发送次数
  uni_mutex_t mutexUart;      
}repeat_data_t;

typedef struct{
  unsigned int cntUartTimeout;  //超时计数器
  unsigned char sequence[64];   //缓冲区
  unsigned char cntLen;         //接收数量
}uart_sequence_t;

typedef struct {
  bool  recvFinish;       //发送使能
  unsigned char serial;   //发送序号 buf[1]
  unsigned short addr;    //指令序号 buf[2] + buf[3] 
  unsigned char flagPlay; //播报标记 buf[4]  
  unsigned char palyAddr; //播报地址 0-随机 1-n 播报序号 buf[5]
}recv_data_t;

typedef struct{
  bool playing;  //1-正在播报
  bool ending;   //1-单个播报完成标记
  bool enPlay;   //1-播报使能
  bool enMute;   //1-静音打开
  unsigned int cntInterval; //播报完成计时器
}audio_paly_t;

typedef enum {
  UART_RECV_HEAD = 0,
  UART_RECV_ONE,
  UART_RECV_TWO,
  UART_RECV_THREE,
  UART_RECV_FOUR,
  UART_RECV_FIRE,
  UART_RECV_CHECKSUM,
  UART_RECV_TAIL
}UART_RECV_RUN_STATE;

typedef struct{
  bool volumeFlag;
  bool mute;
  uni_u32 volumePre;
  uni_u32 volumeLast;
}volumeSave_t;

typedef struct{
  uni_u8 type;        //0-12小时  1-24小时
  uni_u16 addr;
  uni_u16 hour;
  uni_u16 min;
  uni_u16 sec;
}giveTime_t;



/*
  系统功能列表
*/
typedef struct{
  uni_u8 volume;//播报反馈  功能使能
  uni_u8 waitUp;
  uni_u8 custom;
  uni_u8 exit;
  uni_u8 mute;
  uni_u8 once;
  uni_u8 powerOn;
  uni_u8 PAdelay;
  uni_u16 waitUpWorkMark;
}sysParm_t;

typedef struct {
  char data[UART_SEND_MAX];	//串口发送数组
  unsigned char len;		   //发送长度
  unsigned int addr;		    //语音指令序号  
}waitUpData;

#define SLEEP_DELAY   6000    //单次播报休眠时间

bool dosomething = 0;
uni_u32 cntSleep = 0;

repeat_data_t g_uart_repeat = {0};
recv_data_t recvData = {0};
audio_paly_t audioPlay = {0};
static UART_RECV_RUN_STATE g_recv_state = UART_RECV_HEAD;
uart_sequence_t data_sequence = {0};
volumeSave_t volumeData = {0};
giveTime_t GT_Data = {0};
sysParm_t sysParm = {0};

const waitUpData waitUpWork[] = {
   {  {  0x5A, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xEF}, 8, 0x001e},
   {  {  0x5A, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xEF}, 8, 0x001f},
   {  {  0x5A, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0020},
   {  {  0x5A, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0021},
   {  {  0x5A, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0022},
   {  {  0x5A, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0023},
   {  {  0x5A, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0024},
   {  {  0x5A, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0025},
   {  {  0x5A, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0026},
   {  {  0x5A, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xEF}, 8, 0x0027}
};

static bool volumeSave(void);
static bool sysFunSave(void);
static void _costom_volume_setting(unsigned int addr);

/*
  唤醒词屏蔽使能
*/
void _waitUp_work_asr(void)
{
  uni_u8 i = 0;

  for(;i<MAX_WAITUP_WORK;i++){
    if(sysParm.waitUpWorkMark & (1<<i)){
      user_asr_word_disable(waitUpCmdWork[i]);
    }else{
      user_asr_word_enable(waitUpCmdWork[i]);
    }
  }
}


bool _sys_parm_set(recv_data_t value)
{
  bool ret = 0;

  // printf("%x %d %d %d %d\n", value.addr, value.flagPlay, value.palyAddr, value.recvFinish, value.serial);

  switch(value.addr){
    case SYS_VOLUME_SET:
      if(value.flagPlay>=5 && value.flagPlay<=100){
        //音量大小
        volumeData.volumePre = value.flagPlay;
        volumeData.volumeLast = value.flagPlay;
        AudioVolumeSet(volumeData.volumePre);
        volumeSave();
        if(value.palyAddr){
          //是否播报  待开发
          //播报当前设置的音量
        }
        ret = 1;
      }
      break;

    case SYS_PLAY_FB:
      if(value.flagPlay==PLAY_FB_VOLUME){
        if(value.palyAddr){
          sysParm.volume |= AUTO_PLAY;
          // printf("set fb volume %x \n", sysParm.volume);
        }else{
          sysParm.volume &= (~AUTO_PLAY);
          // printf("clean fb volume %x \n", sysParm.volume);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_WAITUP){
        if(value.palyAddr){
          sysParm.waitUp |= AUTO_PLAY;
        }else{
          sysParm.waitUp &= (~AUTO_PLAY);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_CUSTOM){
        if(value.palyAddr){
          sysParm.custom |= AUTO_PLAY;
        }else{
          sysParm.custom &= (~AUTO_PLAY);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_EXIT){
        if(value.palyAddr){
          sysParm.exit |= AUTO_PLAY;
        }else{
          sysParm.exit &= (~AUTO_PLAY);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_MUTE){
        if(value.palyAddr){
          sysParm.mute |= AUTO_PLAY;
        }else{
          sysParm.mute &= (~AUTO_PLAY);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_ONCE){
        if(value.palyAddr){
          sysParm.once |= AUTO_PLAY;
        }else{
          sysParm.once &= (~AUTO_PLAY);
        }
        ret = 1;
      }
      break;

    case SYS_PLAY_LIST:
      if(value.flagPlay==PLAY_FB_VOLUME){
        if(value.palyAddr){
          sysParm.volume |= AUTO_LIST;
        }else{
          sysParm.volume &= (~AUTO_LIST);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_WAITUP){
        if(value.palyAddr){
          sysParm.waitUp |= AUTO_LIST;
        }else{
          sysParm.waitUp &= (~AUTO_LIST);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_CUSTOM){
        if(value.palyAddr){
          sysParm.custom |= AUTO_LIST;
        }else{
          sysParm.custom &= (~AUTO_LIST);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_EXIT){
        if(value.palyAddr){
          sysParm.exit |= AUTO_LIST;
        }else{
          sysParm.exit &= (~AUTO_LIST);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_MUTE){
        if(value.palyAddr){
          sysParm.mute |= AUTO_LIST;
        }else{
          sysParm.mute &= (~AUTO_LIST);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_ONCE){
        if(value.palyAddr){
          sysParm.once |= AUTO_LIST;
        }else{
          sysParm.once &= (~AUTO_LIST);
        }
        ret = 1;
      }
      break;

    case SYS_FUN_SEL:
      if(value.flagPlay==PLAY_FB_VOLUME){
        if(value.palyAddr){
          sysParm.volume |= FUN_EN;
        }else{
          sysParm.volume &= (~FUN_EN);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_WAITUP){
        if(value.palyAddr){
          
          sysParm.waitUp |= FUN_EN;
          // printf("set fun waitup %x\n", sysParm.waitUp);
        }else{
          sysParm.waitUp &= (~FUN_EN);
          // printf("clean fun waitup %x\n", sysParm.waitUp);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_CUSTOM){
        if(value.palyAddr){
          sysParm.custom |= FUN_EN;
        }else{
          sysParm.custom &= (~FUN_EN);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_EXIT){
        if(value.palyAddr){
          sysParm.exit |= FUN_EN;
        }else{
          sysParm.exit &= (~FUN_EN);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_MUTE){
        if(value.palyAddr){
          sysParm.mute |= FUN_EN;
        }else{
          sysParm.mute &= (~FUN_EN);
        }
        ret = 1;
      }else if(value.flagPlay==PLAY_FB_ONCE){
        if(value.palyAddr){
          sysParm.once |= FUN_EN;
        }else{
          sysParm.once &= (~FUN_EN);
        }
        ret = 1;
      }
      break;

    case SYS_WAITUP_SEL:
      if(value.flagPlay>1 && value.flagPlay<=MAX_WAITUP_WORK){
        if(value.palyAddr){
          sysParm.waitUpWorkMark |= (1<<(value.flagPlay-1));
        }else{
          sysParm.waitUpWorkMark &= ~(1<<(value.flagPlay-1));
        }
        _waitUp_work_asr();
        ret = 1;
      }
      break;

    case SYS_DELAY_PA:
      sysParm.PAdelay = value.flagPlay * 5;
      ret = 1;
      break;                   
  }
  if(ret){
    sysFunSave();
  }
  return ret;
}

#if 1   //音量保存
//----------音量保存部分-----------------------
bool volumeSave(void)
{
  bool ret = 0;
  // uni_bool readMute;
  int save_len = 0;
  uni_u32 volumeBuf = 0;
  volumeSave_t volumeRead = {0};

  if (0 != user_flash_init()) {
    return ret;
  }

  volumeData.volumeFlag = 1;

  save_len = user_flash_set_env_blob(BLOB_KEY_VOLUME, &volumeData, sizeof(volumeData));
  if(save_len!=sizeof(volumeData)){
    return ret;
  }

  save_len = user_flash_get_env_blob(BLOB_KEY_VOLUME, &volumeRead, sizeof(volumeRead), &save_len);

  if(volumeRead.volumePre!=volumeData.volumePre){
    return ret;
  }

  ret = 1;
  return ret;
}

void volumeLoad(void)
{
  int save_len = 0;  

  if (0 != user_flash_init()) {
    return;
  }

  save_len = user_flash_get_env_blob(BLOB_KEY_VOLUME, &volumeData, sizeof(volumeData), &save_len);
}

void volumeInit(void)
{
  volumeLoad();

  if(volumeData.volumeFlag==0){
    //no volume data in , set a default data
    volumeData.volumePre = AudioVolumeGet();
    volumeData.volumeLast = volumeData.volumePre;
    volumeData.mute = AudioVolumeGetMute();
    volumeSave();
  }

  AudioVolumeSet(volumeData.volumePre);
  if(volumeData.mute){
    AudioVolumeSetMute(volumeData.mute);
  }
}
//=============音量保存部分===========================
#endif

#if 1 //系统参数保存
//-------------系统功能保存部分-----------------------
bool sysFunSave(void)
{
  bool ret = 0;
  int save_len = 0;
  sysParm_t sysRead = {0};

  // printf("save fun start\n");

  if (0 != user_flash_init()) {
    printf("save fun err\n");
    return ret;
  }
  printf("st %02x %02x %02x %02x %02x %02x %02x\n",  sysParm.exit, sysParm.mute, sysParm.once, 
                                  sysParm.custom, sysParm.powerOn, sysParm.volume, 
                                  sysParm.waitUp); 
  save_len = user_flash_set_env_blob(BLOB_KEY_SYS, &sysParm, sizeof(sysParm));
  if(save_len!=sizeof(sysParm)){
    return ret;
  }
  // printf("write %d %d\n", save_len, sizeof(sysParm));

  save_len = user_flash_get_env_blob(BLOB_KEY_SYS, &sysRead, sizeof(sysRead), &save_len);

  printf("en %02x %02x %02x %02x %02x %02x %02x\n",  sysRead.exit, sysRead.mute, sysRead.once, 
                                  sysRead.custom, sysRead.powerOn, sysRead.volume, 
                                  sysRead.waitUp); 
  ret = 1;
  return ret;
}

int sysFunLoad(void)
{
  int save_len = 0;  

  if (0 != user_flash_init()) {
    return;
  }

  save_len = user_flash_get_env_blob(BLOB_KEY_SYS, &sysParm, sizeof(sysParm), &save_len);
  return save_len;
}

void sysFunInit(void)
{
  int save_len = 0;  

  save_len = sysFunLoad();

  if(save_len!= sizeof(sysParm)){
    //数据错误  复位数据
    sysParm.exit = 0;
    sysParm.mute = 0;
    sysParm.once = 0;
    sysParm.custom = 0;
    sysParm.PAdelay = 0;
    sysParm.powerOn = 0;
    sysParm.volume = 0;
    sysParm.waitUp = 0;
	sysParm.waitUpWorkMark = 0;
  }

	//#define PARM_EXIT				0
	//#define PARM_MUTE				0
	//#define PARM_ONCE				0
	//#define PARM_CUSTOM				0
	#define PARM_PADISPLAY			200
	//#define PARM_POWERON			0
	//#define PARM_VOLUME				0
	//#define PARM_WAITTP				0
	//#define PARM_WAIPWORKMARK		0

	sysParm.exit = PARM_EXIT;
	sysParm.mute = PARM_MUTE;
	sysParm.once = PARM_ONCE;
	sysParm.custom = PARM_CUSTOM;
	sysParm.PAdelay = PARM_PADISPLAY;
	//sysParm.powerOn = PARM_POWERON;
	sysParm.volume = PARM_VOLUME;
	sysParm.waitUp = PARM_WAITTP;
	//sysParm.waitUpWorkMark = PARM_WAIPWORKMARK;

  //----测试功能
  // sysParm.once |= FUN_EN;
  // sysParm.waitUp |= AUTO_LIST|AUTO_PLAY;//AUTO_LIST  AUTO_PLAY FUN_EN
  // sysParm.custom |= AUTO_PLAY;
  // sysParm.waitUpWorkMark |= 1<<2;
  //======================
  printf("%02x %02x %02x %02x %02x %02x %02x\n",  sysParm.exit, sysParm.mute, sysParm.once, 
                                                  sysParm.custom, sysParm.powerOn, sysParm.volume, 
                                                  sysParm.waitUp); 
}
//=============系统功能保存部分=======================
#endif

#if 1 //算分部分
unsigned char chectSum(unsigned char *value, int len)
{
	int i = 0;
	unsigned char result = 0;
	
	for(;i<len;i++){
		result+=value[i];
	}
	
	return result&0xff;
}
#endif

#if 1 //实时播报
//----------------实时报时-----------------------
static void giveTimeInit(void)
{
  uni_u16  i = 0;

  GT_Data.addr = 0;
  GT_Data.hour = 0;
  GT_Data.min = 0;
  GT_Data.sec = 0;
  GT_Data.type = 1;//默认24小时

  for(i=0;i<MAX_YFC_DATA;i++){
    if(uni_strncmp(g_uart_buf[i].CmdName, "give", uni_strlen("give"))==0){
      GT_Data.addr = g_uart_buf[i].addr;
      // printf("giveTime init addr:%d", GT_Data.addr);
    }
  }
}

/*
  播报时间
*/
static void giveTime(uni_u16 hour, uni_u16 min, uni_u16 sec)
{
  char giveTimeStr[32] = {0};
  
  hour--;
  if(hour>23 || min>60 || sec>60){
    return;
  }
  hour += 600;
  min += 600;
  uni_sprintf(giveTimeStr, "[660, %d, 661, %d, 662]",  hour, min);
  // printf("give time %s\n", giveTimeStr);
  user_player_reply_list_in_order(giveTimeStr);//"[660, 600, 661, 603, 662]" 现在是xx点xx分
}
//====================实时报时=======================
#endif

#if 1 //串口部分
//----------------串口发送-----------------------
/*
    开始重复发送指令
*/
static void set_uart_send(unsigned char num, uni_u8 flag)
{
  uni_hal_timer_pause(TIMER5, 1);
  g_uart_repeat.enSend = 1;
  g_uart_repeat.enRepeat = 0;
  g_uart_repeat.cntRepaet = 0;
  g_uart_repeat.num = num;
  g_uart_repeat.bexecute = 0;
  
  //修改发送数据
  g_uart_repeat.serial++;
  if(g_uart_repeat.serial==0){
    g_uart_repeat.serial = 1;
  }
  if(!flag){
    uni_memcpy(g_uart_repeat.data, g_uart_buf[num].data, 8);
    g_uart_repeat.data[1] = g_uart_repeat.serial;
    g_uart_repeat.data[6] = chectSum(g_uart_repeat.data, 6);
  }else{
    uni_memcpy(g_uart_repeat.data, waitUpWork[num].data, 8);
    g_uart_repeat.data[1] = g_uart_repeat.serial;
    g_uart_repeat.data[6] = chectSum(g_uart_repeat.data, 6);
  }


  user_uart_send(g_uart_repeat.data, 8); //发送一帧数据

  uni_hal_timer_pause(TIMER5, 0);
  uni_hal_timer_start(TIMER5);
}

static void set_uart_report(void)
{
  g_uart_repeat.data[0] = 0x5a;
  g_uart_repeat.data[1] = 0x00;
  g_uart_repeat.data[2] = recvData.addr>>8;
  g_uart_repeat.data[3] = recvData.addr&0xff;
  g_uart_repeat.data[4] = recvData.flagPlay;
  g_uart_repeat.data[5] = recvData.palyAddr;
  g_uart_repeat.data[6] = chectSum(g_uart_repeat.data, 6);
  g_uart_repeat.data[7] = 0xef;
  user_uart_send(g_uart_repeat.data, 8); //发送一帧数据
}

/*
    停止发送指令
*/
static void clean_uart_send(void)
{
  uni_hal_timer_pause(TIMER5, 1);
  g_uart_repeat.enSend = 0;
  g_uart_repeat.enRepeat = 0;
  g_uart_repeat.cntRepaet = 0;
  g_uart_repeat.num = 0;
}

static void uart_sequence_clean(void)
{
  uni_memset(data_sequence.sequence, 0, 32);
  data_sequence.cntLen = 0;
}

static void uart_sequence_sprint(unsigned char *buf, int len)
{
  if( (len + data_sequence.cntLen ) >= 32){
    len = 31 - data_sequence.cntLen;
  }

  uni_memcpy(data_sequence.sequence + data_sequence.cntLen, buf, len);
  data_sequence.cntLen += len;
}

/*
    urat 序列接收
*/
static void uart_sequence(unsigned char *buf, int len)
{
  unsigned char i = 0,j=0;
  uint16_t addr;
  uint8_t flagPlay, palyAddr, serial;
  
  if(recvData.recvFinish){
    uart_sequence_clean();
    return;
  }

  uart_sequence_sprint(buf, len);//拼接缓冲
  data_sequence.cntUartTimeout = 0;

  g_recv_state = UART_RECV_HEAD;

  #if 0 //debug
  printf("uart sequence %d ", data_sequence.cntLen);
  for(i=0;i<data_sequence.cntLen;i++){
    printf("%02x ", data_sequence.sequence[i]);
  }
  printf("\n");
  #endif

  i = 0;
_GOTO_PARSE_RESET:
  switch (g_recv_state){
    case UART_RECV_HEAD:
      i = j;
      for (; i < data_sequence.cntLen; i++){
        if (UART_HEAT_1 == data_sequence.sequence[i]){
          break;
        }
      }
      if (i >= data_sequence.cntLen){
        break;
      }
      g_recv_state = UART_RECV_ONE;
      i++;
    case UART_RECV_ONE:   //serial
      if (i >= data_sequence.cntLen){
        break;
      }
      serial = data_sequence.sequence[i];
      j = i;
      g_recv_state = UART_RECV_TWO;
      i++;
    case UART_RECV_TWO:   //addrH
      if (i >= data_sequence.cntLen){
        break;
      }
      g_recv_state = UART_RECV_THREE;
      i++;
    case UART_RECV_THREE:   //addrL
      if (i >= data_sequence.cntLen){
        break;
      }
      addr = (data_sequence.sequence[i-1]<<8) + data_sequence.sequence[i];
      g_recv_state = UART_RECV_FOUR;
      i++;
     case UART_RECV_FOUR:     //play
      if (i >= data_sequence.cntLen){
        break;
      }
      flagPlay = data_sequence.sequence[i];
      g_recv_state = UART_RECV_FIRE;
      i++;
    case UART_RECV_FIRE:      //play addr
      if (i >= data_sequence.cntLen) {
        break;
      }
      palyAddr = data_sequence.sequence[i];
      g_recv_state = UART_RECV_CHECKSUM;
      i++;      
    case UART_RECV_CHECKSUM:  //sum
      if(i >= data_sequence.cntLen){
        break;
      }
      if(chectSum((data_sequence.sequence+j-1), 6)!=data_sequence.sequence[i]){
        g_recv_state = UART_RECV_HEAD;
        goto _GOTO_PARSE_RESET;
      }
      g_recv_state = UART_RECV_TAIL;
      i++;
    case UART_RECV_TAIL:	//tail
      if (i >= data_sequence.cntLen) {
        break;
      }
      if (UART_TAIL_1 != data_sequence.sequence[i]) {
        g_recv_state = UART_RECV_HEAD;
        goto _GOTO_PARSE_RESET;
      }

      recvData.recvFinish = 1;  //单次接收处理完成
      recvData.addr = addr;
      recvData.serial = serial;
      recvData.flagPlay = flagPlay;
      recvData.palyAddr = palyAddr;

      if(recvData.addr == GT_Data.addr){
        //检测到报时
		    recvData.flagPlay ++;
        GT_Data.hour = recvData.flagPlay;
        GT_Data.min = palyAddr;
        GT_Data.sec = 0;
      }
      g_recv_state = UART_RECV_HEAD;

      //单次处理完成 丢弃剩下的数据
      uart_sequence_clean();
      break;
    default:
      break;
  }
}

/*
  超时清除函数
*/
void uart_dispose(void)
{
  if(data_sequence.cntLen){
    if(data_sequence.cntUartTimeout++>200){
      data_sequence.cntUartTimeout = 0;
      uart_sequence_clean();
    }
  }
}
 

static void uart_recv_dispose(void)
{
  unsigned int i = 0;
  unsigned int assNum = 0;
  uni_u8 flagReport = 0;

  if(!recvData.recvFinish){
    return;
  }
  recvData.recvFinish = 0;

  uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
  //判断是否同一个序号  序号未零 主动播报行为
  if(recvData.serial==0 ){
    if(recvData.addr >= ADDR_SYS_MIN && recvData.addr<= ADDR_SYS_MAX){
      //系统设置指令
      if(_sys_parm_set(recvData)){
        //返回一条串口指令 表示已经修改
        flagReport = 1;
      }
    }else if(recvData.addr >= ADDR_WAITUP_MIN && recvData.addr<= ADDR_WAITUP_MAX){
      //唤醒词播报
      if(recvData.flagPlay){
        //主动播报 可以中断之前的播报
        audioPlay.enPlay = 1;
        for(i=0;i<MAX_WAITUP_WORK;i++){
          if(recvData.addr == waitUpWork[i].addr){
            assNum = i;
            if(recvData.palyAddr==0){
              user_player_reply_list_random(g_uart_buf[0].playList);
            }else{
              user_player_reply_list_num(g_uart_buf[0].playList, recvData.palyAddr-1);
            }
          }
        }
      }
    }else{
      //主动播放指令
      if(recvData.flagPlay){
        //主动播报 可以中断之前的播报
        audioPlay.enPlay = 1;
        for(i=0;i<MAX_YFC_DATA;i++){
          if(recvData.addr==g_uart_buf[i].addr){
            assNum = i;
            if( uni_strncmp(g_uart_buf[assNum].CmdName, "tem", uni_strlen("tem"))==0 ||
                uni_strncmp(g_uart_buf[assNum].CmdName, "tim", uni_strlen("tim"))==0){
              //组合句播放
              if(recvData.palyAddr==2){
                //重复播报
                user_player_reply_list_in_order(g_uart_buf[assNum].replyList);
                flagReport = 1;
              }else if(recvData.palyAddr==1){
                //首次播报
                user_player_reply_list_in_order(g_uart_buf[assNum].playList);
                flagReport = 1;
              }else if(recvData.palyAddr==0){
                //随机播报 首次播报
                user_player_reply_list_in_order(g_uart_buf[assNum].playList);
                flagReport = 1;
              }
            }else if(uni_strncmp(g_uart_buf[assNum].CmdName, "give", uni_strlen("give"))==0){
                //时间播报
                giveTime(GT_Data.hour, GT_Data.min, GT_Data.sec);
                flagReport = 1;
            }else if(uni_strncmp(g_uart_buf[assNum].CmdName, "volume", uni_strlen("volume"))==0){
                //音量播报
                _costom_volume_setting(assNum);
                flagReport = 1;
            }else{
              //单句播放
              if(recvData.palyAddr==0){
                //随机播放
                user_player_reply_list_random(g_uart_buf[assNum].playList);
                flagReport = 1;
              }else{
                //指定播放
                user_player_reply_list_num(g_uart_buf[assNum].playList, recvData.palyAddr-1);
                flagReport = 1;
              }
            }
            break;
          }
        }
      }
    }
  }else if(g_uart_repeat.serial == recvData.serial && g_uart_repeat.bexecute==0){
    g_uart_repeat.bexecute = 1;
    //不能中断之前的播报
    if(recvData.flagPlay){
      //播报识别的语音
      if(audioPlay.enPlay){
        if(recvData.addr >= ADDR_WAITUP_MIN && recvData.addr<= ADDR_WAITUP_MAX){
          for(i=0;i<MAX_WAITUP_WORK;i++){
            if(recvData.addr == waitUpWork[i].addr){
              assNum = i;
              if(recvData.palyAddr==0){
                user_player_reply_list_random(g_uart_buf[0].playList);
              }else{
                user_player_reply_list_num(g_uart_buf[0].playList, recvData.palyAddr-1);
              }
            }
          }
        }else if(recvData.addr == g_uart_buf[g_uart_repeat.num].addr){
          if( uni_strncmp(g_uart_buf[g_uart_repeat.num].CmdName, "tem", uni_strlen("tem"))==0 ||
              uni_strncmp(g_uart_buf[g_uart_repeat.num].CmdName, "tim", uni_strlen("tim"))==0){
            //组合句播放
            if(recvData.palyAddr==2){
              //重复播报
              user_player_reply_list_in_order(g_uart_buf[g_uart_repeat.num].replyList);
            }else if(recvData.palyAddr==1){
              //首次播报
              user_player_reply_list_in_order(g_uart_buf[g_uart_repeat.num].playList);
            }else if(recvData.palyAddr==0){
              //随机播报 首次播报
              user_player_reply_list_in_order(g_uart_buf[g_uart_repeat.num].playList);
            }
          }else if(uni_strncmp(g_uart_buf[g_uart_repeat.num].CmdName, "give", uni_strlen("give"))==0){
            //时间播报
            giveTime(GT_Data.hour, GT_Data.min, GT_Data.sec);
          }else if(uni_strncmp(g_uart_buf[g_uart_repeat.num].CmdName, "volume", uni_strlen("volume"))==0){
            //音量播报
            _costom_volume_setting(g_uart_repeat.num);
          }else{
            //单句播放
            if(recvData.palyAddr==0){
              //随机播放
              user_player_reply_list_random(g_uart_buf[g_uart_repeat.num].playList);
            }else{
              //指定播放
              user_player_reply_list_num(g_uart_buf[g_uart_repeat.num].playList, recvData.palyAddr-1);
            }
          }
        }
      }
    }
  }

  if(g_uart_repeat.enSend){
    //清楚缓冲区
    clean_uart_send(); 
  }
  if(flagReport){
    set_uart_report();//主动指令需要返回一个对应的数据
  }  
  uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
}

#endif

#if 1 //逻辑部分
/*
    中断不能带阻塞  原子锁 信号量 log打印都不能
*/
static void _timer_cb(TIMER_INDEX idx)
{
  g_uart_repeat.enRepeat = 1;
  g_uart_repeat.cntRepaet++;
}

static void uart_repeat_dispose()
{
  uni_pthread_mutex_lock(g_uart_repeat.mutexUart);

  if(g_uart_repeat.enSend){     //重复发送
    if(g_uart_repeat.enRepeat){
      g_uart_repeat.enRepeat = 0;
      if(g_uart_repeat.cntRepaet>3){
        //停止发送
        g_uart_repeat.enSend = 0;
        g_uart_repeat.cntRepaet = 0;
      }else{
        //发送数据
        user_uart_send(g_uart_repeat.data, 8);
        uni_hal_timer_pause(TIMER5, 0);  //重复发送
        uni_hal_timer_start(TIMER5);
      }
    }
  }

  uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
}


/*
  防止两次播报连续重复进行
*/
static void audio_play_dispose(void)
{
  if(audioPlay.ending){
    audioPlay.cntInterval++;
    if(audioPlay.cntInterval>30){
      audioPlay.cntInterval = 0;
      audioPlay.ending = 0;
      audioPlay.enPlay = 1;
      audioPlay.playing = 0;
    }
  }
}

static void waitupOnce(void)
{
  if(sysParm.once&FUN_EN){
    //单次播放
    if(dosomething){
      if(cntSleep++>SLEEP_DELAY){
        cntSleep = 0;
        user_asr_goto_sleep();
      }
    }
  }
}

/*
  uart重复发送
  uart接收完成
  线程
*/
static void _uart_repeat_send_task(void *args) {

  while (1) {
    //接收完成处理
    uart_recv_dispose();    
    //重复发送处理
    uart_repeat_dispose();
    //语音二次播报处理d
    audio_play_dispose();
    //序列串口处理函数
    uart_dispose();

    waitupOnce();

    uni_msleep(1);
  }
}
#endif

#if 1 //识别回调函数
static void _custom_setting_cb(USER_EVENT_TYPE event,
                               user_event_context_t *context) {

  event_custom_setting_t *setting = NULL;
  unsigned int i = 0;
  
  if(context){
    setting = &context->custom_setting;
    LOGT(TAG, "user command aa: %s", setting->cmd);

    if(sysParm.once&FUN_EN){
      //单次播放
      if(dosomething){
        return;
      }
      dosomething = 1;
      cntSleep = 0;
    }

    for(i=0;i<MAX_YFC_DATA;i++){
      if (0 == uni_strcmp(setting->cmd, g_uart_buf[i].CmdName)){
        if (0 == uni_strcmp("muteClean", g_uart_buf[i].CmdName)){
          if(! (sysParm.mute & FUN_EN)){
            if(!(sysParm.mute & AUTO_PLAY)){
              //静音功能 自动完成
              user_player_speaker_unmute();
              if(audioPlay.enMute){
                audioPlay.enMute = 0;
                user_player_reply_list_num(g_uart_buf[i].playList, 0);
              }else{
                audioPlay.enMute = 0;
                user_player_reply_list_num(g_uart_buf[i].playList, 1);
              }
              volumeData.mute = 0;
              volumeSave();
            }
          }

          uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
          set_uart_send(i, 0); //设置发送标记
          uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);

        }else if (0 == uni_strcmp("muteSet", g_uart_buf[i].CmdName)){
          
          if(! (sysParm.mute & FUN_EN)){
            if(!(sysParm.mute & AUTO_PLAY)){
              // 静音功能 自动完成
              audioPlay.enMute = 1;
              volumeData.mute = 1;
              user_player_reply_list_random(g_uart_buf[i].playList);
              volumeSave();
            }
          }
          uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
          set_uart_send(i, 0); //设置发送标记
          uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
        }else{
          if(! (sysParm.custom & FUN_EN)){
            if(!(sysParm.custom & AUTO_PLAY)){
              user_player_reply_list_random(g_uart_buf[i].playList);
            }
          }
          //指令词识别
          uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
          set_uart_send(i, 0); //设置发送标记
          uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);

        }
        break;
      }
    }
  }
}

static void _custom_audio_play_start(USER_EVENT_TYPE event,
                               user_event_context_t *context){

  event_audio_play_t *playing = NULL;
  uni_u8 i = 0;

  if (context){
    playing = &context->audio_play;
    LOGT(TAG, "_custom_audio_play_start: %s", playing->file_name);

    audioPlay.playing = 1;
    audioPlay.enPlay = 0;
    audioPlay.ending = 0;
    audioPlay.cntInterval = 0;

	  user_gpio_set_value(GPIO_NUM_A28, PA_EN_LV);
    
    for(i=0;i<STUDY_PLAY_LIST;i++){
      if(0 == uni_strcmp(playing->file_name, studyPlayList[i])){
        audioPlay.playing = 0;
        audioPlay.enPlay = 1;
        audioPlay.ending = 1;
      }
    }
    uni_msleep(sysParm.PAdelay);//部分功放需要延时

  }
}


static void _custom_audio_play_end(USER_EVENT_TYPE event,
                               user_event_context_t *context) {

  event_audio_end_t *ending = NULL;

  if (context) {
    ending = &context->audio_end;
    LOGT(TAG, "_custom_audio_play_end aa");

	  user_gpio_set_value(GPIO_NUM_A28, PA_DIS_LV);
    audioPlay.playing = 0;
    audioPlay.enPlay = 1;
    audioPlay.ending = 1;
    audioPlay.cntInterval = 0;
    if(audioPlay.enMute){
      user_player_speaker_mute();
    }
  }
}

/*
    音量设置函数
*/
static void _costom_volume_setting(unsigned int addr)
{

  uni_s32 volume_buf = 0;

  volume_buf = AudioVolumeGet();

  switch (addr){
    case VOL_MAX:
      if(volume_buf==VOLUME_MAX){
        user_player_reply_list_num(g_uart_buf[VOL_MAX].playList, 1);	//已是最大音量
      }else{
		    user_player_set_volume_max();
        user_player_reply_list_num(g_uart_buf[VOL_MAX].playList, 0);		//调到最大音量
      }
      volumeData.volumePre = VOLUME_MAX;
      break;
    case VOL_MID:
      
      if(volume_buf==VOLUME_MID){
        user_player_reply_list_num(g_uart_buf[VOL_MID].playList, 1);	  //已是最大音量
      }else{
		    user_player_set_volume_mid();  
        user_player_reply_list_num(g_uart_buf[VOL_MID].playList, 0);		//调到最大音量
      }
      volumeData.volumePre = VOLUME_MID;
      break;
    case VOL_MIN:
      if(volume_buf==VOLUME_MIN+5){
        user_player_reply_list_num(g_uart_buf[VOL_MIN].playList, 1);
      }else{
		    user_player_set_volume_min();
        user_player_reply_list_num(g_uart_buf[VOL_MIN].playList, 0);
      }
      volumeData.volumePre = VOLUME_MIN+5;
      break;
    case VOL_UP:
      if(volume_buf==VOLUME_MAX){
        user_player_reply_list_num(g_uart_buf[VOL_MAX].playList, 1);
        volumeData.volumePre = VOLUME_MAX;
      }else{
        volumeData.volumePre += 15;
        if(volumeData.volumePre>VOLUME_MAX){
          volumeData.volumePre = VOLUME_MAX;  
        }
		    AudioVolumeSet(volumeData.volumePre);
        user_player_reply_list_num(g_uart_buf[VOL_UP].playList, 0);		
      }
      break;
    case VOL_DOWN:
      if(volume_buf==VOLUME_MIN+5){
        user_player_reply_list_num(g_uart_buf[VOL_MIN].playList, 1);
        volumeData.volumePre = VOLUME_MIN+5;
      }else{
        if(volumeData.volumePre< VOLUME_MIN+5+15){
          volumeData.volumePre = VOLUME_MIN+5; 
        }else{
          volumeData.volumePre -= 15;
        }
        AudioVolumeSet(volumeData.volumePre);  
        user_player_reply_list_num(g_uart_buf[VOL_DOWN].playList, 0);
      }
      break;
    default:
      break;
  }
  
  if(volume_buf!=volumeData.volumePre){
    volumeSave();
  }
}

static void _costom_volume_cb(USER_EVENT_TYPE event,
                               user_event_context_t *context) {
  event_volume_setting_t *volume = NULL;
  unsigned int i = 0;
  if (context) {
    volume = &context->voluem_setting;
    LOGT(TAG, "_costom_volume_cb %s", volume->cmd);
  
    if(sysParm.volume&FUN_EN){
      //语音功能禁止
      return;
    }

    if(sysParm.once&FUN_EN){
      //单词播报
      if(dosomething){
        return;
      }
      dosomething = 1;
      cntSleep = 0;
    }

    for(i=0;i<MAX_YFC_DATA;i++){
       if (0 == uni_strcmp(volume->cmd, g_uart_buf[i].CmdName)){
        
        if(!(sysParm.volume&AUTO_PLAY)){
          //主动修改并播报
          _costom_volume_setting(i);
        }

        uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
        set_uart_send(i, 0); //设置发送标记
        uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
        break;
       }
    }
  }
}

static void _costom_sleeping_cb(USER_EVENT_TYPE event,
                               user_event_context_t *context) {
  event_goto_sleeping_t *sleep = NULL;
  unsigned int i = 0;

  if (context) {
    sleep = &context->goto_sleeping;
    LOGT(TAG, "_costom_sleeping_cb %s", sleep->cmd);

    if(sysParm.once&FUN_EN){
      //单次播报
      //如果已经有动作 就不做退出播报，如果唤醒后没有做指令动作，退出需要播报
      if(dosomething){
        dosomething = 0;
      }else{
        if(!(sysParm.exit&AUTO_PLAY)){
          //主动播报
          user_player_reply_list_random(sleep->reply_files);
        }
      }
    }else{
      if(!(sysParm.exit&AUTO_PLAY)){
        //主动播报
        user_player_reply_list_random(sleep->reply_files);
      }
    }

    uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
    set_uart_send(1, 0); //设置发送标记
    uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
  }
}

static void _costom_waitup_cb(USER_EVENT_TYPE event,
                               user_event_context_t *context) {
  event_goto_awakend_t *waitup = NULL;
  unsigned int i = 0, serial;

  if (context) {
    waitup = &context->goto_awakend;
    LOGT(TAG, "_costom_waitup_cb");

    //单轮播报
    if(sysParm.once&FUN_EN){
      dosomething = 0;
      cntSleep = 0;
    }

    //选择唤醒词
    for(i=0;i<MAX_WAITUP_WORK;i++){
      if (0 == uni_strcmp(waitUpCmdWork[i], waitup->word_str)){
        printf("costom_waitup_cb %d\n", i);
        serial = i;
        break;
      }
    }
    if(i>9){
      i = 0;
      serial = 0;
    }
    if(!(sysParm.waitUp & AUTO_PLAY)){
      //唤醒自动播报
      if(sysParm.waitUp & AUTO_LIST){
        //对应播报
        if(serial<MAX_WAITUP_REPLT){
          user_player_reply_list_num(waitup->reply_files, serial);      
        }
      }else{
        //随机播报
        user_player_reply_list_random(waitup->reply_files);
      }
    }else{
      //唤醒不播报
    }

    uni_pthread_mutex_lock(g_uart_repeat.mutexUart);
    if(i<MAX_WAITUP_WORK){
      set_uart_send(i, 1); //设置发送标记
    }else{
      set_uart_send(0, 1); //设置发送标记
    }
    uni_pthread_mutex_unlock(g_uart_repeat.mutexUart);
  }
}

static void _register_event_callback(void){
  user_event_subscribe_event(USER_GOTO_AWAKENED, _costom_waitup_cb);  
  user_event_subscribe_event(USER_CUSTOM_SETTING, _custom_setting_cb);
  user_event_subscribe_event(USER_AUDIO_PLAY_START, _custom_audio_play_start);
  user_event_subscribe_event(USER_AUDIO_PLAY_END, _custom_audio_play_end);
  user_event_subscribe_event(USER_VOLUME_SETTING, _costom_volume_cb);
  user_event_subscribe_event(USER_GOTO_SLEEPING, _costom_sleeping_cb);
}
#endif

int hb_auto_gpio(void){
  user_gpio_init();
  user_gpio_set_mode(GPIO_NUM_A25, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_A25, 0);
  user_gpio_set_mode(GPIO_NUM_A26, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_A26, 0);
  user_gpio_set_mode(GPIO_NUM_A27, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_A27, 0);
  user_gpio_set_mode(GPIO_NUM_A28, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_A28, PA_DIS_LV);
  user_gpio_set_mode(GPIO_NUM_B2, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_B2, 0);
  user_gpio_set_mode(GPIO_NUM_B3, GPIO_MODE_OUT);
  user_gpio_set_value(GPIO_NUM_B3, 0);

  user_uart_init(uart_sequence);//uart_sequence//_uart_recv_cb

  _register_event_callback();

  sysFunInit();
  _waitUp_work_asr();
  volumeInit();  //控制音量
 
  giveTimeInit();

  //新建一个线程  作为串口协议  连续返送回调处理
  uni_pthread_t pid;
  thread_param param;
  param.stack_size = STACK_SMALL_SIZE;
  param.priority   = OS_PRIORITY_HIGH;
  strncpy(param.task_name, "uartRepeat", sizeof(param.task_name) - 1);
  uni_pthread_create(&pid, &param, _uart_repeat_send_task, NULL);       //传入参数  作为语音播报用  
  uni_pthread_detach(pid);

  audioPlay.enPlay = 1;

  //定时器
  uni_hal_timer_init(TIMER5, 100*1000, true, _timer_cb);
  // uni_hal_timer_start(TIMER5);
  uni_hal_timer_pause(TIMER5, 1);
  //原子锁
  uni_pthread_mutex_init(&g_uart_repeat.mutexUart);//语音播报

  printf(YFC_FW_VER);

  return 0;
}




 